#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>

/********************************************
 *@brief  设置串口通信速率
 *@param  fd     类型 int  打开串口的文件句柄
 *@param  speed  类型 int  串口速度
 *@return  void
********************************************/

//串口速率的映射关系
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,
		B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = { 38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200,
		9600, 4800, 2400, 1200, 300, };

//设置串口的速率
void set_speed(int fd, int speed) {
	int i;
	int status;
	struct termios Opt;

	tcgetattr(fd, &Opt);

	for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {

		if (speed == name_arr[i]) {

			tcflush(fd, TCIOFLUSH);

			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);

			status = tcsetattr(fd, TCSANOW, &Opt);

			if (status != 0) {
				perror("tcsetattr fd1!");
			}
			return;
		}

		tcflush(fd, TCIOFLUSH);
	}
}
/******************************************
 *@brief   设置串口数据位，停止位和效验位
 *@param  fd       类型  int  打开的串口文件句柄
 *@param  databits 类型  int 数据位   取值 为 7 或者8
 *@param  stopbits 类型  int 停止位   取值为 1 或者2
 *@param  parity   类型  int  效验类型 取值为N,E,O,,S
******************************************/
int set_parity(int fd, int databits, int stopbits, int parity) {
	struct termios options;

	if (tcgetattr(fd, &options) != 0) {
		perror("SetupSerial 1");
		return 0;
	}

	options.c_cflag &= ~CSIZE;

  //设置数据位数
	switch (databits) {
	case 7:
		options.c_cflag |= CS7;
		break;
	case 8:
		options.c_cflag |= CS8;
		break;
	default:
		fprintf(stderr, "Unsupported data size\n");
		return 0;
	}

	switch (parity) {
	case 'n':
	case 'N':
		options.c_cflag &= ~PARENB; /* Clear parity enable */
		options.c_iflag &= ~INPCK; /* Enable parity checking */
		break;
	case 'o':
	case 'O':
		options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'e':
	case 'E':
		options.c_cflag |= PARENB; /* Enable parity */
		options.c_cflag &= ~PARODD; /* 转换为偶效验*/
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'S':
	case 's': /*as no parity*/
		options.c_cflag &= ~PARENB;
		options.c_cflag &= ~CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported parity\n");
		return 0;
	}

	//设置停止位
	switch (stopbits) {
	case 1:
		options.c_cflag &= ~CSTOPB;
		break;
	case 2:
		options.c_cflag |= CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported stop bits\n");
		return 0;
	}

	if (parity != 'n') {
		options.c_iflag |= INPCK;
	}

	options.c_cc[VTIME] = 150;
	options.c_cc[VMIN] = 0;

	tcflush(fd, TCIFLUSH);

	if (tcsetattr(fd, TCSANOW, &options) != 0) {
		perror("SetupSerial 3");
		return 0;
	}

	return 1;
}

/************************************************
 *@breif 打开串口
 *@param Dev 设备的名称 类型 char *
************************************************/
int OpenDev(char *Dev) {
	int fd = open(Dev, O_RDWR); //| O_NOCTTY | O_NDELAY

	if (-1 == fd) {
		perror("Can't Open Serial Port");
		return -1;
	} else {
		return fd;
	}
}

/***********************************************
 *@send_command 发送一条旋转的命令
 *@param fd 设备号 类型 int
 *@param label 舵机号 类型 int
 *@param angle 旋转的角度 类型 int
 *@param rotate_time 旋转的时间 类型 int
 *@return void
***********************************************/
void send_command(int fd, int label,int angle,int rotate_time) {
  char buf[];
  int size;
  write(fd,buf,size);
  write(fd,'\r',1);
  write(fd,'\n',1);
}


/**********************************************
 *@read_command 查看现在的状态
 *@param fd 设备号 类型 int
 *@param lable 舵机号 类型 int
 *@param angle 角度 类型 int *
 *@param rotate_time 旋转花费的时间 int *
 *@return void
**********************************************/
void read_command(int fd, int label, int *angle, int *rotate_time) {
  int nread;
  char buf[512];
  
  if((nread = read(fd, buf, 512)) > 0) {
    *angle = 1000;
    *rotate_time = 100;
  }
}

/********************************************
 *@breif main 程序的入口
 *******************************************/
int main(int argc, char **argv) {
	int fd;
	int nread;
	char buff[512];
	char *dev = "/dev/ttyS1";

	fd = OpenDev(dev);

	if (fd > 0)
		set_speed(fd, 19200);
	else {
		printf("Can't Open Serial Port!\n");
		exit(0);
	}

	if (set_parity(fd, 8, 1, 'N') == 0) {
		printf("Set Parity Error\n");
		exit(1);
	}
  
	close(fd);
  return 0;
}

